package com.acme.bankapp.service.bank;

import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Calendar;

import com.acme.bankapp.domain.bank.Account;
import com.acme.bankapp.domain.bank.Bank;
import com.acme.bankapp.domain.bank.ClientRegistrationListener;
import com.acme.bankapp.domain.bank.SavingsAccount;
import com.acme.bankapp.domain.bank.CheckingAccount;
import com.acme.bankapp.domain.bank.Client;
import com.acme.bankapp.domain.bank.Gender;
import com.acme.bankapp.domain.bank.BankException;
import com.acme.bankapp.mail.EMail;
import com.acme.bankapp.mail.EMailService;

public class BankService {
	private static EMailService emailService = new EMailService();

	@SuppressWarnings("serial")
	public static class PrintClientListener implements
			ClientRegistrationListener, Serializable {
		public void onClientAdded(Client c) {
			System.out.println("New client " + c.getClientSalutation() + ": "
					+ c.getAccount().maximumAmountToWithdraw());
		}
	}

	@SuppressWarnings("serial")
	public static class EmailNotificationListener implements
			ClientRegistrationListener, Serializable {
		public void onClientAdded(Client c) {
			emailService.sendNotificationEmail(new EMail(c));
		}
	}

	@SuppressWarnings("serial")
	public static class DebugListener implements ClientRegistrationListener,
			Serializable {
		public void onClientAdded(Client c) {
			Calendar calendar = Calendar.getInstance();
			SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
			System.out.println("Client " + c.getClientSalutation() + " "
					+ format.format(calendar.getTime()));
		}
	}

	public static Bank createBankWithListeners() throws InterruptedException {
		ClientRegistrationListener[] listeners = new ClientRegistrationListener[3];
		listeners[0] = new PrintClientListener();
		listeners[1] = new EmailNotificationListener();
		listeners[2] = new DebugListener();
		Bank bank = new Bank(listeners);
		generateClients(bank, 3);
		return bank;
	}

	static void addClient(Bank bank, Client client) {
		if (bank != null)
			bank.addClient(client);
	}

	public static void generateClients(Bank bank, int number)
			throws InterruptedException {
		for (int i = 0; i < number; i++) {
			Client client = generateClient();
			addClient(bank, client);
		}
		System.out.println("Start hard task simulation");
		Thread.sleep(10000);
		System.out.println("End of simulation");
		stopEmailNotification();
	}

	public static Client generateClient() {
		String[][] names = {
				{ "Andrey", "Ivan", "Gleb", "Vasiliy", "Oleg", "Stanislav" },
				{ "Diana", "Olga", "Alexandra", "Natalia", "Maria" } };
		String[] mails = { "a@mail.com", "b@mail.com", "c@mail.com",
				"d@mail.com", "e@mail.com", "f@mail.com" };

		Account newAccount;
		try {
			newAccount = Math.random() < 0.5 ? new SavingsAccount(
					Math.random() * 100 - 10) : new CheckingAccount(
					Math.random() * 100 - 10, Math.random() * 100 - 10);
		} catch (IllegalArgumentException e) {
			newAccount = Math.random() < 0.5 ? new SavingsAccount(0)
					: new CheckingAccount(0, 0);
		}
		Gender newGender = Math.random() < 0.5 ? Gender.MALE : Gender.FEMALE;
		String newName = names[newGender.ordinal()][((int) (Math.random() * 100))
				% names[newGender.ordinal()].length];
		String newEMail = mails[((int) (Math.random() * 100)) % mails.length];

		return new Client(newName, newGender, newAccount, newEMail);
	}

	static void modifyBank(Bank bank) throws BankException {
		if (bank != null) {
			for (int i = 0; i < bank.numClients(); i++) {
				if (Math.random() < 0.5) {
					double amount = Math.random() * 5;
					if (Math.random() < 0.5) {
						bank.getClient(i).getAccount().withdraw(amount);
					} else {
						bank.getClient(i).getAccount().deposit(amount);
					}
				}
			}
		}
	}

	static void printMaximumAmountToWithdraw(Bank bank) {
		if (bank != null) {
			System.out.println("List of clients:");
			for (int i = 0; i < bank.numClients(); i++) {
				System.out.println(bank.getClient(i).getClientSalutation()
						+ ": "
						+ bank.getClient(i).getAccount()
								.maximumAmountToWithdraw());
			}
		}
	}

	static void printClients(Bank bank) {
		if (bank != null) {
			System.out.println("List of clients:");
			StringBuffer sbuffer = new StringBuffer();
			for (int i = 0; i < bank.numClients(); i++) {
				sbuffer.append(bank.getClient(i) + "\n");
			}
			System.out.println(sbuffer);
			System.out.println("");
		}
	}

	public static void stopEmailNotification() {
		emailService.close();
	}
}
